package com.starlink.utils;

import java.io.*;
import java.util.concurrent.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ZipUtils2 {

    private static final int THREAD_POOL_SIZE = 5; // Number of threads to use

    private static Object lock = new Object(); // Lock object for synchronization

    /**
     * 将对应文件夹下的文件及文件夹写入对应文件夹目录下
     *
     * @param out
     * @param file
     * @param pareFileName
     */
    public static void putZipFile(final ZipOutputStream out, File file, String pareFileName) {
        try {
            ExecutorService executor = Executors.newFixedThreadPool(THREAD_POOL_SIZE);

            File files[] = file.listFiles();
            for (final File dirFile : files) {
                if (dirFile.isDirectory()) {
                    String newParentName = pareFileName + dirFile.getName() + File.separator;
                    ZipEntry zipEntry = new ZipEntry(newParentName);

                    synchronized (lock) {
                        out.putNextEntry(zipEntry);
                    }

                    executor.submit(new Runnable() {
                        @Override
                        public void run() {
                            putZipFile(out, dirFile, newParentName);
                        }
                    });
                } else {
                    String newParentName = pareFileName + dirFile.getName();
                    FileInputStream fi = new FileInputStream(dirFile);
                    BufferedInputStream origin = new BufferedInputStream(fi);

                    ZipEntry entry = new ZipEntry(newParentName);

                    synchronized (lock) {
                        out.putNextEntry(entry);

                        byte[] buffer = new byte[1024];
                        int count;
                        while ((count = origin.read(buffer)) != -1) {
                            out.write(buffer, 0, count);
                        }
                    }

                    origin.close();
                }
            }

            executor.shutdown();
            executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
            throw new RuntimeException("压缩文件异常", e);
        }
    }
}
